//
// Created by Soar Qin on 2017/9/7.
// Copyright (c) 2017 Soar Qin. All rights reserved.
//

#include "common.hh"

#include "kcp_client.hh"

#include "kcp_endpoint.hh"
#include "timer.hh"
#include "ip_addr.hh"

extern "C" {
#include "core/async/private/ikcp.c.inc"
}

namespace core::async {

int kcpcb(const char *buf, int len, ikcpcb *kcp, void *user) {
    return 0;
}

class KCPChecker: public Timer {
public:
    KCPChecker(Loop &loop, KCPClient *c): Timer(loop), client_(c) {}

protected:
    void onTimer() override {
    }

private:
    KCPClient *client_;
};

struct KCPClientContext {
    KCPEndpoint *endpoint = nullptr;
    ikcpcb *kcp = nullptr;
    IPAddr addr;
    KCPChecker *checker = nullptr;
    uint32_t conv = 0;
};

KCPClient::KCPClient(KCPEndpoint *endpoint): context_(new KCPClientContext) {
    context_->endpoint = endpoint;
    context_->checker = new KCPChecker(endpoint->getLoop(), this);
}

KCPClient::~KCPClient() {
    ikcp_release(context_->kcp);
    delete context_;
}

bool KCPClient::init(uint32_t conv, const IPAddr &addr) {
    auto *c = ikcp_create(conv, this);
    if (c == nullptr) return false;
    ikcp_wndsize(c, 2048, 2048);
    ikcp_nodelay(c, 1, 20, 2, 1);
    c->output = kcpcb;
    context_->kcp = c;
    context_->addr = addr;
    context_->conv = conv;
    return true;
}

void KCPClient::write(const void *buf, size_t size) {
    ikcp_send(context_->kcp, (const char*)buf, (long)size);
}

void KCPClient::input(const void *buf, size_t size) {
    ikcp_input(context_->kcp, (const char*)buf, (long)size);
}

}
